"use strict";

/*
 维度的查询导出基础方法..
 */

//,include 	= radon.use('Include')
//,DataCenterGo = include.use('DataCenter')
//,config		= include.use('DataCenterConfig')
//,EXPORT		= include.use('DataCenterExport')

var radon = require('radon');
var include = radon.use('Include');
var sysUtil = require('util');
var util = radon.util;
var DataGo = require('./DataCenterGo');
var DataCenterGo = DataGo.base;
var config = DataGo.config;
var EXPORT = require('./DataCenterHelper').export;
var MongoCriteria	= require('./MongoCriteria').base;

var mongoCriteria = new MongoCriteria();
var datacenter = new DataCenterGo();

var hawkConfig = radon.config('hawk');
const USER_COST_AMEND = radon.config('user_cost_amend') || {};

/*
 维度的go查询.
 */
//function query(helper, param, format, isExport, cb) {
function* query(configParam)
{
	var helper = configParam.helper;
	var param = configParam.param;
	var format = configParam.format;
	var isExport = configParam.isExport;
	var cb = configParam.cb;
	var timeout;

	if(isExport)
	{
		helper.filterMetricsField(true);
		timeout = hawkConfig && hawkConfig.export_timeout || 3600000;
	}
	else
	{
		timeout = hawkConfig && hawkConfig.timeout || 300000;
	}

	var options = helper.getOptions(true);
	var type = options && options['type'];
	var query = config('export.' + type);
	if(!query) {
		radon.throw(17001);
	}


	var metricKeys = param.keys || query['keys']
		,metricDims = query['dims'] || []
		,fullRecord = options['full_record'];

	// 转换组合要查询的指标
	var fields = yield datacenter.processFields(query, options);
	fields = fields.metric;
	if(!fields || !fields.length) {
		radon.throw(17002);
	}

	// 排序字段参数处理
	var sort = datacenter.processOrder(options);
	sort = sort && sort.metric;
	var page = options.page;
	var size = options.size;
	if(!page && page != 0) {
		page = 1;
	}

	if(!size) {
		size = 20;
	}

	var offset;
	var hasPage = (page > 0 && size >0);

	var baseOption = util.extend({}, options.base, {
		keys: metricKeys
		,dims: metricDims
		,query_type: options.ctype || 'default'
	});

	// 指标过滤条件
	var metricWhere = options.metric_where;
	if(metricWhere) {
		if(metricWhere.begintime) {
			baseOption.begin_time = metricWhere.begintime;
			metricWhere.begintime = undefined;
		}

		if(metricWhere.endtime) {
			baseOption.end_time = metricWhere.endtime;
			metricWhere.endtime = undefined;
		}
	}

	var conds = util.extend({}, metricWhere || {}, options.dim_where || {}, options.addon_where || {});
	var goOptions = {
		keys: metricKeys
		,metrics: fields
		,conds: conds
		,'must_keys': fullRecord && (sort || metricKeys.length < 2) ? 1 : 0
		,'in_keys_order': sort === undefined || sort['mongo'] === undefined ? 0 : 1
		,'limit': 15000
		,'use_total': 1
	};

	if(sort)
	{
		goOptions.orderby = sort;
	}

	if(timeout)
	{
		baseOption.timeout = timeout;
	}

	var data;
	if(options.query_items)
	{
		let op = util.clone(goOptions);
		op.use_item = 1;
		if(hasPage)
		{
			offset = (page -1) * size;
			// 分页大小
			op.limit = size;
			// 记录偏移计数
			op.offset = offset;
			// 分页查询统计数据
			data = yield datacenter.queryGo(op, baseOption);
		}
		else
		{
			data = yield datacenter.queryGo(op, baseOption);
		}
	}

	var amount;
	if(options.query_amount)
	{
		goOptions.use_amount = 1;
		amount = yield datacenter.queryGo(goOptions, baseOption);
	}

	var result = {
		total: data.total
		,items: data && data.items
		,amount: amount && amount.amount
		,fillValue: fillZeroData(fields)
	};

	if(hasPage) {
		result.page = page;
		result.size = size;
	}

	if(!result.items) {
		result.items = [];
	}

	if(format) {
		yield format(result.items)
	}
	if(cb) {
		yield cb(result);
	}

	return result;
}

/*
 填充0数据
 */
function fillZeroData(fields) {
	var result = {};
	if(fields && fields.length) {
		fields.forEach(function(prop) {
			result[prop] = 0
		})
	}
	return result;
}

function exportFile(name, helper) {
	var fn = name;
	if(helper && helper.getParam) {
		var p = helper.getParam();
		var start = new Date(p.begin() * 1000);
		var end = new Date(p.end() * 1000);
		start = util.date('Ymd',start);
		end = util.date('Ymd', end);
		fn = name + start + '-' + end;
	}

	return fn;
}

/*
 通用的导出方法.
 */
var innerProcessExport = util.generator(function*(type, data, param, helper, cbParam) {
	//处理item时, 没有把helper传过来的.
	if (helper && helper.file) {
		cbParam = helper;
		helper = null;
	}
	switch (type) {
		// 获取导出文件名
		case 'file':
			return (yield exportFile(cbParam.file, helper));
		// 初始化指标顺序, 并且可以格式化数据
		case 'cols':
			// 处理列表数据
			if(cbParam.format) {
				yield cbParam.format(data.items);
			}
			return cbParam.cols || [];
			break;
		case 'head':
			return cbParam.head || [];
			break;
		case 'item':
			var ret = [];
			if(cbParam.item && cbParam.item.length) {
				cbParam.item.forEach(function(name) {
					ret.push(data.hasOwnProperty(name) ? data[name] : '—');
				});
			}
			if(cbParam.itemFormat) {
				ret = yield cbParam.itemFormat(data);
			}
			return ret;
			break;
	}
});

var exportMethod = util.generator(function*(param, isOffline) {
	var self = this;
	var result = param.result;
	var exportParam = param.exportParam || [];
	var exportConfig = param.exportConfig;
	if(exportConfig) {
		exportParam.push(
			util.generator(function*() {
				var args = Array.prototype.slice.call(arguments);
				args.push(exportConfig);
				return (yield innerProcessExport.apply(self, args));
			})
		);
	}

	exportParam.push(result);
	exportParam.push(isOffline);
	return yield EXPORT.apply(param.helper, exportParam);
});

var offline_export = function*(param) {
	return yield exportMethod(param, true);
};

/*
 通用的导出方法.
 */
var processExport = function*(type, data, param, helper, cbParam) {
	//处理item时, 没有把helper传过来的.
	if(!helper.filterOr) {
		cbParam = helper;
		helper = null;
	}
	switch (type) {
		// 获取导出文件名
		case 'file':
			return (yield exportFile(cbParam.file, helper));
			break;
		// 初始化指标顺序, 并且可以格式化数据
		case 'cols':
			// 处理列表数据
			if (cbParam.format) {
				yield cbParam.format(data.items);
			}
			return cbParam.cols || [];
			break;
		case 'head':
			return cbParam.head || [];
			break;
		case 'item':
			return cbParam.item || [];
			break;
	}
};

exports.query = query;
exports.export = exportMethod;
exports.offline_export = offline_export;
exports.processExport = processExport;

/*
 返回账户的今天消费
 */
var todayCost = function*(UserId, type) {
	var options = {
		'begin': Date.now(),
		'end': Date.now(),
		'type': type
	};

	var result = yield getSumCost(UserId, options);
	if(result.items.length == 1) {
		result =  result.items[0];
	}
	return result && result.cost || 0;
};

exports.TodayCost = todayCost;

/*
 反账户的总消费
 */
var totalCost = function*(UserId, type) {
	var options = {
		'begin': 0,
		'end': Date.now(),
		'type': type
	};

	var result = yield getSumCost(UserId, options);
	if(result.items.length == 1) {
		result =  result.items[0];
	}
	let total_cost = result && result.cost || 0;
	let user_id = result && result.user_id;
	
	// 修正历史数据
	total_cost = amendUserCost(user_id, total_cost);
	
	return total_cost;
}

exports.TotalCost = totalCost;

// 因为历史数据原因，现在接口查出来的悠久历史客户数据不正确，需要修正历史总消耗
function amendUserCost(user_id, total_cost)
{
	if (user_id && +USER_COST_AMEND[user_id])
	{
		total_cost += USER_COST_AMEND[user_id];
	}
	return total_cost;
}
exports.amendUserCost = amendUserCost;

/*
 @option object  查询的参数
 options{
 begin: 0,
 end: 0,
 'type': type: [1,3],
 key: [1,3],
 orderby: [name: true],
 limit: 20
 }

 @UserId: int/[int] 要查询的账号id
 @begin:  查询的开始时间 , 可选
 @end:    查询的结束时间 , 可选
 @消费类型: 有RTB 移动消耗. 1 = rtb, 4 = mobile, 默认是[1,4]
 @key: 	维度，类型数组，可选，默认是user_id
 @orderby  用于排序的列，可以是纬度或指标, 数组，可选
 [{date: true},{cost: false}]
 @limit:  数量，可选
 */
var getSumCost = function*(UserId, options) {
	options = options || {};
	var begin = options['begin'],
		end = options['end'],
		type = options['type'],
		key = options['key'],
		orderby = options['orderby'],
		limit = options['limit'] || 10000000,
		offset = options['offset'] || 0,
		cond = options['cond'] || {},
		metrics = options['metrics'] || ['true_cost', 'proxy_cost', 'cost'];
	if(begin) {
		mongoCriteria.begin(begin);
	}
	if(end) {
		mongoCriteria.end(end);
	}
	if(!type) {
		type = [0,1,4];
	}
	else if(!Array.isArray(type)) {
		type = [type];
	}

	if(!Array.isArray(UserId)) {
		UserId = [UserId];
	}
	//自定义维度，默认user_id
	if(!key){
		key = ['user_id']
	}else if(!Array.isArray(key)){
		key = [key];
	}
	//自定义排序列
	if(orderby){
		if(!Array.isArray(orderby)){
			orderby = [orderby];
		}
		var order = [];
		orderby.forEach(function(item){
			for(var val in item){
				if(item.hasOwnProperty(val)) {
					order.push({
						'name': val,
						'asc': item[val]
					});
				}
			}
		});
	}

	var user = yield include.getUser();
	var goOptions = {
		"keys": key,
		"conds": util.extend({}, cond, {user_id: {$in: UserId}, channel_type_id:{$in: type}, channel_id: {$gt: 10000}}),
		//"use_amount": true,
		"use_item": 1,
		"metrics": metrics,
		"limit": limit,
		"debug": 0,
		"offset": offset,
		"query_type": user.isMaster() ? 'admin': 'default',
		"use_total": true
	};

	if(order && order.length){
		goOptions.orderby = order;
	}
	if(begin) {
		goOptions.begin_time = mongoCriteria.begin();
	}else{
		goOptions.begin_time = 0;
	}
	if(end) {
		goOptions.end_time = mongoCriteria.end();
	}

	var finance = yield datacenter.queryGo(goOptions);
	return {
		total: finance.total,
		items: finance.items
	};
}

exports.goQuery = function*(options) {
	options = options || {};
	var begin = options['begindate'],
		end = options['enddate'],
		type = options['type'],
		key = options['key'],
		orderby = options['order'],
		limit = options['limit'] || 10000000,
		offset = options['offset'] || 0,
		cond = options['cond'] || {},
		metrics = options['metrics'];

	if(!metrics || !metrics.length)
	{
		return {total: 0, items: []};
	}

	if(begin) {
		mongoCriteria.begin(begin);
	}
	if(end) {
		mongoCriteria.end(end);
	}

	if(!type) {
		type = [0,1,4];
	}
	else if(!Array.isArray(type)) {
		type = [type];
	}

	//自定义维度，默认user_id
	if(!key){
		key = ['user_id']
	}else if(!Array.isArray(key)){
		key = [key];
	}
	//自定义排序列
	let order = [];
	if(orderby){
		let orders = orderby.split(",");
		if (orders && orders.length) {
			for(let i = orders.length - 1; i >= 0; i--)
			{
				let sortStr = orders[i].split("|");
				order.push({name: sortStr[0], asc: +sortStr[1] == 1})
			}
		}
		else
		{
			order.push({name: 'impressions_0', acs: true});
		}
	}

	let goOptions = {
		"keys": key,
		"conds": util.extend({}, {channel_type_id:{$in: type}, channel_id: {$gt: 10000}}, cond),
		"use_amount": true,
		"use_item": 1,
		"metrics": metrics,
		"limit": limit,
		"debug": 0,
		"offset": offset,
		"use_total": true
	};

	if(order && order.length)
	{
		goOptions.orderby = order;
	}
	if(begin)
	{
		goOptions.begin_time = mongoCriteria.begin();
	}
	else
	{
		goOptions.begin_time = 0;
	}
	if(end)
	{
		goOptions.end_time = mongoCriteria.end();
	}

	return yield datacenter.queryGo(goOptions);
};

exports.getSumCost = getSumCost;

